﻿
namespace Patterns4Net.Tests.PatternEnforcer.Core.Patterns.Regression
{
    using System;
    using Mono.Cecil;
    using NUnit.Framework;
    using Patterns4Net.Core.CecilExtensions;
    using Patterns4Net.Core.Patterns;
    using Patterns4Net.PatternEnforcer.Core;
    using Patterns4Net.PatternEnforcer.Core.Patterns;

    [TestFixture]
    public class NullObjectsCheckerTest : PatternCheckerTestBase
    {
        [Test]
        [TestCase(typeof(NullChecker1))]
        [TestCase(typeof(NullChecker2))]
        [TestCase(typeof(TooComplexNullChecker))]
        [TestCase(typeof(NullCalculatorThatDoesNotOverride))]
        [TestCase(typeof(NullCalculator))]
        [TestCase(typeof(NullCalculatorThatContainsFields))]
        public void RunAllTests(Type type)
        {
            this.TestChecker(
                new NullObjectChecker(), 
                type,
                new NullObject(type.GetTypeDefinition()));
        }

        [PatternTest(true)]
        public class NullChecker1 : IChecker<TypeDefinition>
        {
            public CheckerResult Check(TypeDefinition subject)
            {
                return new CheckerResult(new CheckerResult[0]);
            }
        }

        [PatternTest(true)]
        public class NullChecker2 : IChecker<TypeDefinition>
        {
            public CheckerResult Check(TypeDefinition subject)
            {
                return CheckerResult.CreateSimpleResult(true, new CheckerError(string.Empty));
            }
        }

        [PatternTest(false)]
        public class TooComplexNullChecker : IChecker<TypeDefinition>
        {
            public CheckerResult Check(TypeDefinition subject)
            {
                int count = 0;
                for (int i = 0; i < 10; i++)
                {
                    if (i % 2 == 0 && (i * i) % 3 == 0)
                    {
                        count++;
                    }
                }

                return CheckerResult.CreateSimpleResult(count > 2, new CheckerError(string.Empty));
            }
        }

        public abstract class CalculatorBase
        {
            public virtual int Plus(int a, int b)
            {
                return a + b;
            }

            public abstract int Mul(int a, int b);
        }

        [PatternTest(false)]
        public class NullCalculatorThatDoesNotOverride : CalculatorBase
        {
            public override int Mul(int a, int b)
            {
                return 0;
            }
        }

        [PatternTest(false)]
        public class NullCalculatorThatContainsFields : CalculatorBase
        {
            private int result = 3;

            public override int Plus(int a, int b)
            {
                return this.result;
            }

            public override int Mul(int a, int b)
            {
                return this.result;
            }
        }

        [PatternTest(true)]
        public class NullCalculator : CalculatorBase
        {
            public override int Plus(int a, int b)
            {
                return 0;
            }

            public override int Mul(int a, int b)
            {
                return 0;
            }
        }
    }
}
